import 'dart:io';

import 'package:desktop_drop/desktop_drop.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:silk_flutter/model/file_item.dart';
import 'package:silk_flutter/utils/anyhow_parser.dart';
import 'package:silk_flutter/utils/data_size.dart';
import 'package:silk_flutter/widgets/operation_button.dart';
import 'package:silk_flutter/widgets/toast_container.dart';
import 'package:silk_flutter/widgets/window_header.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:window_manager/window_manager.dart';

import '../src/rust/api/simple.dart';
import '../utils/persistent.dart';

class DecodePage extends StatefulWidget {
  final _outDirKey = "output_dir";

  const DecodePage({super.key});

  @override
  State<DecodePage> createState() => _DecodePageState();
}

class _DecodePageState extends State<DecodePage> {
  final _outputDirController = TextEditingController();
  final _toast = FToast();
  final ValueNotifier<List<FileItem>> _files = ValueNotifier([]);
  final ValueNotifier<bool> _dragging = ValueNotifier(false);

  @override
  void initState() {
    super.initState();
    _toast.init(context);
    Persistent.getString(widget._outDirKey).then(
      (value) => setState(() {
        _outputDirController.text = value;
      }),
    );
  }

  @override
  void dispose() {
    _files.dispose();
    _dragging.dispose();
    _outputDirController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          if (Platform.isWindows)
            GestureDetector(
              behavior: HitTestBehavior.translucent,
              onPanStart: (_) => windowManager.startDragging(),
              child: const SizedBox(height: 48, child: WindowHeader()),
            ),
          Expanded(
            child: DropTarget(
              child: _FileTable(files: _files, dragging: _dragging),
              onDragDone: (details) async {
                final files = await drag2File(details);
                if (files.isEmpty) {
                  return;
                }
                final currentFiles = _files.value;
                for (var file in files) {
                  if (currentFiles.any((item) => item.path == file.path)) {
                    continue;
                  }
                  _files.value.add(file);
                }
              },
              onDragExited: (_) => _dragging.value = false,
              onDragEntered: (_) => _dragging.value = true,
              onDragUpdated: (details) {
                _dragging.value = true;
              },
            ),
          ),
          Container(
            color: Colors.grey.shade100,
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                ValueListenableBuilder<List<FileItem>>(
                  valueListenable: _files,
                  builder: (context, files, _) {
                    return Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text("已选择: ${files.length} 个文件"),
                        Column(
                          children: [
                            Text(
                              "总大小: ${DataSize.formatFileSize(files.map((item) {
                                return item.size;
                              }).fold(0, (i1, i2) => i1 + i2))}",
                            ),
                            const SizedBox(height: 4),
                            InkWell(
                              onTap: _showHelp,
                              child: Text(
                                "点我查看帮助",
                                style: TextStyle(
                                  color: Colors.blue,
                                  fontSize: 12,
                                ),
                              ),
                            ),
                          ],
                        ),
                      ],
                    );
                  },
                ),
                const SizedBox(height: 16),
                Row(
                  children: [
                    Expanded(
                      flex: 1,
                      child: OperationButton(
                        text: "选择文件",
                        textColor: Colors.white,
                        backgroundColor: Colors.brown,
                        onPressed: () async {
                          var files = await pickFiles();
                          if (files.isEmpty) {
                            return;
                          }
                          final currentFiles = _files.value;
                          for (var file in files) {
                            if (currentFiles.any(
                              (item) => item.path == file.path,
                            )) {
                              continue;
                            }
                          }
                          _files.value = [...currentFiles, ...files];
                        },
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 1,
                      child: OperationButton(
                        text: "输出目录",
                        textColor: Colors.black,
                        backgroundColor: Colors.white,
                        onPressed: _pickOutputDir,
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 3,
                      child: TextField(
                        controller: _outputDirController,
                        readOnly: true,
                        style: const TextStyle(fontSize: 14), // 字体不能太大
                        textAlignVertical: TextAlignVertical.center,
                        decoration: InputDecoration(
                          contentPadding: const EdgeInsets.symmetric(
                            vertical: 4,
                            horizontal: 12,
                          ),
                          focusedBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(4),
                            borderSide: const BorderSide(
                              color: Color(0xFFDDE0E4),
                              width: 1,
                            ),
                          ),
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(4),
                          ),
                          enabledBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(4),
                            borderSide: const BorderSide(
                              color: Color(0xFFDDE0E4),
                              width: 1,
                            ),
                          ),
                          suffixIcon: InkWell(
                            onTap: _openDir,
                            child: Tooltip(
                              message: "打开目录",
                              child: const Icon(
                                Icons.folder,
                                color: Colors.grey,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 1,
                      child: OperationButton(
                        text: "开始转换",
                        textColor: Colors.white,
                        backgroundColor: Colors.lightGreen,
                        onPressed: () async {
                          final files = _files.value;
                          if (files
                              .where(
                                (item) =>
                                    item.status != ConvertStatus.completed,
                              )
                              .isEmpty) {
                            showToast(_toast, "没有需要转换的文件");
                            return;
                          }
                          if (_outputDirController.text.isEmpty) {
                            showToast(_toast, "请选择输出目录");
                            return;
                          }
                          for (var file in files) {
                            if (file.status == ConvertStatus.converting ||
                                file.status == ConvertStatus.completed) {
                              continue;
                            }
                            _item2wav(file);
                          }
                        },
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      flex: 1,
                      child: OperationButton(
                        text: "清空列表",
                        textColor: Colors.white,
                        backgroundColor: Colors.redAccent,
                        onPressed: () {
                          _files.value = [];
                        },
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  void _item2wav(FileItem item) async {
    var silkPath = item.path;
    var pcmPath = "${_outputDirController.text}/${item.name}-temp.pcm";
    var wavPath = "${_outputDirController.text}/${item.name}.wav";

    // 更新状态
    final currentFiles = _files.value;
    final index = currentFiles.indexOf(item);
    if (index != -1) {
      item.status = ConvertStatus.converting;
      currentFiles[index] = item;
      _files.value = [...currentFiles];
    }

    try {
      await silkDecode(silkPath: silkPath!, pcmPath: pcmPath);
      await pcm2Wav(pcmPath: pcmPath, wavPath: wavPath);
      deleteFilePath(path: pcmPath);

      // 更新状态为完成
      final updatedFiles = _files.value;
      final updatedIndex = updatedFiles.indexOf(item);
      if (updatedIndex != -1) {
        item.status = ConvertStatus.completed;
        updatedFiles[updatedIndex] = item;
        _files.value = [...updatedFiles];
      }
    } on AnyhowException catch (e) {
      setState(() {
        // 更新状态为失败
        item.status = ConvertStatus.failed;
        item.error = e.parseMessage();
      });
    } catch (e) {
      setState(() {
        // 更新状态为失败
        item.status = ConvertStatus.failed;
        item.error = e.toString();
      });
    }
  }

  void _pickOutputDir() async {
    String? outputDir = await FilePicker.platform.getDirectoryPath();
    if (outputDir == null) {
      return;
    }
    _outputDirController.text = outputDir;
    await Persistent.save(widget._outDirKey, _outputDirController.text);
  }

  void _openDir() async {
    if (_outputDirController.text.isEmpty) {
      showToast(_toast, "请选择输出目录");
      return;
    }
    var uri = Uri.file(_outputDirController.text, windows: Platform.isWindows);
    if (!await launchUrl(uri)) {
      showToast(_toast, "无法打开文件目录或目录不存在");
    }
  }

  void _showHelp() {
    showModalBottomSheet(
      context: context,
      constraints: BoxConstraints(
        maxWidth: double.infinity,
        maxHeight: MediaQuery.heightOf(context) * 0.9,
      ),
      isScrollControlled: true,
      builder: (context) {
        return SizedBox(
          width: double.infinity,
          child: SfPdfViewer.asset("assets/help.pdf"),
        );
      },
    );
  }
}

class _FileTable extends StatefulWidget {
  final ValueNotifier<List<FileItem>> files;
  final ValueNotifier<bool> dragging;

  const _FileTable({required this.files, required this.dragging});

  @override
  State<_FileTable> createState() => _FileTableState();
}

class _FileTableState extends State<_FileTable> {
  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: widget.dragging,
      builder: (context, drag, child) {
        return ValueListenableBuilder<List<FileItem>>(
          valueListenable: widget.files,
          builder: (context, files, _) {
            return Stack(
              children: [
                if (drag)
                  Positioned.fill(
                    child: Container(color: Colors.grey.shade400),
                  ),
                SingleChildScrollView(
                  child: SizedBox(
                    width: double.infinity,
                    child: DataTable(
                      columns: const [
                        DataColumn(
                          label: Text("文件名"),
                          headingRowAlignment: MainAxisAlignment.center,
                        ),
                        DataColumn(
                          label: Text("类型"),
                          headingRowAlignment: MainAxisAlignment.center,
                        ),
                        DataColumn(
                          label: Text("文件大小"),
                          headingRowAlignment: MainAxisAlignment.center,
                        ),
                        DataColumn(
                          label: Text("状态"),
                          headingRowAlignment: MainAxisAlignment.center,
                        ),
                        DataColumn(
                          label: Text("操作"),
                          headingRowAlignment: MainAxisAlignment.center,
                        ),
                      ],
                      rows: files.asMap().entries.map((entry) {
                        final index = entry.key;
                        final file = entry.value;
                        return DataRow(
                          cells: [
                            DataCell(Center(child: Text(file.name))),
                            DataCell(Center(child: Text(file.type))),
                            DataCell(
                              Center(
                                child: Text(DataSize.formatFileSize(file.size)),
                              ),
                            ),
                            DataCell(
                              Center(
                                child: TooltipVisibility(
                                  visible: file.isError() && file.error != "",
                                  child: Tooltip(
                                    message: file.error,
                                    child: Text(file.status),
                                  ),
                                ),
                              ),
                            ),
                            DataCell(
                              Center(
                                child: Tooltip(
                                  message: "删除",
                                  child: IconButton(
                                    icon: const Icon(
                                      Icons.delete,
                                      color: Colors.redAccent,
                                    ),
                                    onPressed: () {
                                      final currentFiles = [
                                        ...widget.files.value,
                                      ];
                                      currentFiles.removeAt(index);
                                      widget.files.value = currentFiles;
                                    },
                                  ),
                                ),
                              ),
                            ),
                          ],
                        );
                      }).toList(),
                    ),
                  ),
                ),
              ],
            );
          },
        );
      },
    );
  }
}
